﻿/*
These are modified by 罗勇刚, just for more shotcut,but only usable when you open a file to edit!!
Maybe I'll change this.
*/
module poseidon.model.misc;

private import dwt.all;
private import Analyzer.XML.Core;
private import dwt.internal.converter;
private import std.thread;
private import std.string;


extern (C) {
	void _searchenv( char *filename, char *varname, char *pathname );
}


class _ShortCut {
	// used in preference dialog to sort
	static int sortdirection;
	static int sorttype;
	enum{
		SORT_INDEX,	//sort by input sequence;
		SORT_NAME,	// sort by name
		SORT_KEY,	// sort by keyname
	}

	public int Index;
	char[] 	name;

	private	char[]	defaultShortCut;
	private	char[]	currentShortCut;
	
	this() {
		name="";
		Index=0;
		defaultShortCut="";
		currentShortCut="";
		sorttype=SORT_INDEX;
	}
	
	public void dump() {
		std.stdio.writefln("\r\n === dump of short cut ===");
		std.stdio.writefln("Index:"~std.string.toString(Index));
		std.stdio.writefln("name : " ~ name);
		std.stdio.writefln("Default Shortcut  : " ~ this.defaultShortCut);
		std.stdio.writefln("Current Shortcut  : " ~ this.currentShortCut);
		debug{
			Util.trace("\r\n === dump of short cut ===");
			Util.trace("name : " ~ name);
			Util.trace("Default Shortcut  : " ~ this.defaultShortCut);
			Util.trace("Current Shortcut  : " ~ this.currentShortCut);
		}
	}
	
	bool match(uint mask, uint code) {
		std.stdio.writefln("The maskcode that will be matched is "~this.keyname(mask,code));
		std.stdio.writefln("The current shortcut is "~currentShortCut);
		bool isMatched=std.string.cmp(this.keyname(mask,code),currentShortCut)==0;
		if (isMatched){
			std.stdio.writefln("Matched!");
		}
		return isMatched;
	}

	public bool SetShortcut(uint mask,uint code){
		char[] TempShortCut;
		TempShortCut=keyname(mask,code);
		if (TempShortCut.length==1) return false;
		this.currentShortCut=TempShortCut;
		return true;
	}
	static public char[] keyname(uint mask,uint code) {
		char[] txt = null;
		if(mask & DWT.CTRL)
			txt = "CTRL";
		if(mask & DWT.ALT)
			txt ~= txt ? "+ALT" : "ALT";
		if(mask & DWT.SHIFT)
			txt ~= txt ? "+SHIFT" : "SHIFT";
		
		if(code < 256) {
			if(txt)
				txt ~= "+";
			// convert to upper case
			txt ~= cast(char)code - ('a' - 'A');
		}else if(code >= (DWT.F1)){
			int num = code - DWT.F1 + 1;
			if(txt)
				txt ~= "+";
			txt ~= "F"~std.string.toString(num);
		}
		return txt;
	}

	public uint GetMask(){
		uint mask;
		mask=0;
		if (this.find("ALT")) mask|=DWT.ALT;
		if (this.find("CTRL")) mask|=DWT.CTRL;
		if (this.find("SHIFT")) mask|=DWT.SHIFT;
		return mask;
	}
	public char[] keyname(){
		return this.currentShortCut;
	}
	
	bool find(char[] key){
		// std.c.stdio.printf(std.string.toStringz("find string "~key~"\n"));
		// std.c.stdio.printf(std.string.toStringz("find string "~this.currentShortCut~"\n"));
		return std.string.find(this.currentShortCut,key)!=-1;
	}

	public bool find(char key){
		// std.c.stdio.printf("find Character.\n");
		return (currentShortCut[currentShortCut.length-1]==key);
	}

	void load(XMLnode node) {
		XMLattrib attrib;

		attrib = node.getAttribEx("index","");
		// std.stdio.writefln(attrib.GetValue()~"\n");
		this.Index=std.string.atoi(attrib.GetValue());

		attrib = node.getAttribEx("name", "");
		this.name = attrib.GetValue();
		validCheck(this.name);


		attrib =  node.getAttribEx("default", "");
		this.defaultShortCut = attrib.GetValue();
		validCheck(this.defaultShortCut);

		attrib = node.getAttribEx("current", "");
		this.currentShortCut = attrib.GetValue();
		validCheck(this.currentShortCut);
		dump();
	}
	
	// reset to default value
	void reset() {
		this.currentShortCut=this.defaultShortCut;
	}
	
	public void save(XMLnode node) {
		node.addAttrib("index",std.string.toString(Index));
		node.addAttrib("name", name);
		node.addAttrib("default", this.defaultShortCut);
		node.addAttrib("current", this.currentShortCut);
	}
	
	public _ShortCut clone() {
		_ShortCut result = new _ShortCut();
		result.name = this.name;
		result.defaultShortCut = this.defaultShortCut;
		result.currentShortCut = this.currentShortCut;
		return result;		
	}
	
	/** 
	 * use index/name/keyname to sort
	 */
	int opCmp(Object obj){
		_ShortCut o = cast(_ShortCut)obj;
		int result = 0;
		if(sorttype == SORT_INDEX){
			result =o.Index-this.Index;
		}else
		if(sorttype == SORT_NAME) {
			result = std.string.cmp(this.name, o.name);
		}else{
			result = std.string.cmp(this.keyname, o.keyname);
		}
		if(sortdirection == DWT.UP)
			return result;
		return (0 - result);
	}
	
	private void validCheck(inout char[] string) {
		if(string is null) string = "";
	}
}

/**
 * customized tools enties
 */
class ToolEntry // 外部工具
{
	char[] name = "";
	char[] cmd = "";
	char[] dir = "";
	char[] args = "";
	
	static ToolEntry	lastTool;
	
	// Before Excute the customized command, save files
	boolean savefirst = true;
	boolean hideWnd = false;
	
	// capture the output 
	boolean capture = true;	
	
	private void validCheck(inout char[] string) {
		if(string is null) string = "";
	}
	
	void load(XMLnode node) {
		XMLattrib attrib;
		attrib = node.getAttribEx("name", "");
		name = attrib.GetValue();
		attrib = node.getAttribEx("savefirst", "1");
		savefirst = std.string.atoi(attrib.GetValue())>0;
		attrib = node.getAttribEx("hideWnd", "1");
		hideWnd = std.string.atoi(attrib.GetValue())>0;
		attrib = node.getAttribEx("capture", "1");
		capture = std.string.atoi(attrib.GetValue())>0;
		attrib = node.getAttribEx("dir", "");
		dir = attrib.GetValue();		
		attrib = node.getAttribEx("cmd", "");
		cmd = attrib.GetValue();
		attrib = node.getAttribEx("args", "");
		args = attrib.GetValue();
		
		validCheck(dir);
		validCheck(cmd);
		validCheck(name);
		validCheck(args);
		
		dump();
	}
	
	void save(XMLnode node) {
		node.addAttrib("name", name);
		node.addAttrib("savefirst", std.string.toString(savefirst));
		node.addAttrib("hideWnd", std.string.toString(hideWnd));
		node.addAttrib("capture", std.string.toString(capture));
		node.addAttrib("dir", dir);
		node.addAttrib("cmd", cmd);
		node.addAttrib("args", args);
	}
	
	public ToolEntry clone() {
		ToolEntry result = new ToolEntry();
		result.name = name;
		result.cmd = cmd;
		result.dir = dir;
		result.args = args;
		result.savefirst = savefirst;
		result.hideWnd = hideWnd;
		result.capture = capture;
		return result;		
	} 
	public void dump() {
		debug{
			Util.trace("name : " ~ name);
			Util.trace("dir : " ~ dir);
			Util.trace("args : " ~ args);
			Util.trace("cmd : " ~ cmd); 
		}
	}
}


class FindOption {
	boolean	bRegexp;
	boolean	bCase = true;
	boolean	bWord = true;
	boolean	bWrap = true;
	boolean	bForward = true;
	char[] strFind = "";
	char[] strReplace = "";
	int _scope = 0;
	
	public FindOption clone(){
		FindOption fop = new FindOption();
		fop.bRegexp = bRegexp;
		fop.bCase = bCase;
		fop.bWord = bWord;
		fop.bWrap = bWrap;
		fop.bForward = bForward;
		fop.strFind = strFind;
		fop.strReplace = strReplace;
		fop._scope = _scope;
		
		return fop;
	} 
}

class ThreadEx : Thread
{
	int delegate(Object) _dg;
	Object args;
	this(Object args, int delegate(Object) dg)
	{
		this.args = args;
		this._dg = dg;
	}
	
	// override the base class method
	int run()
    {
    	if(_dg)
	    	return _dg(args);
	    return -1;
    }
}
